
import React, { useEffect, useRef, useState } from 'react';
import { Space, Button, message } from 'antd';

type CanvasElementState = HTMLCanvasElement | null;
interface CoordinateState {
  x: number;
  y: number;
}
type EventsType = 'click' | 'move' | 'dblclick';

const CanvasImage = () => {

  // 当前画图坐标
  const [areaPoints, setAreaPoints] = useState<CoordinateState[]>([])
  const areaPointsRef = useRef<CoordinateState[]>([])
  areaPointsRef.current = areaPoints;
  // 当前画图坐标
  const [currentMovePoint, setCurrentMovePoint] = useState<CoordinateState | null>(null)

  // 当前保存图片
  const currentUrlRef = useRef<string>('')
  // 当前是否允许画图以
  const drawFlag = useRef<boolean>(false);
  // 画图类型
  const drawTypeFlag = useRef<string>('area');

  const exitTypes = useRef<string[]>([])

  // clearImage
  const clearAll = () => {
    exitTypes.current = []
    currentUrlRef.current = ''
    const canvasEle: CanvasElementState = document.querySelector('#myCanvas');
    if (canvasEle) {

      const ctx = canvasEle.getContext('2d');
      if (ctx) {
        // 清除画布
        ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
      }
    }
  }
  

  // 保存图片
  const saveImage = () => {
    const canvasEle: CanvasElementState = document.querySelector('#myCanvas');
    if (canvasEle) {
      const url = canvasEle.toDataURL("image/png")
      currentUrlRef.current = url;
    }
  }
  // 结束画图
  const stopDraw = () => {
    drawFlag.current = false;
    setTimeout(() => {
      saveImage()
      setAreaPoints([])
      setCurrentMovePoint(null)
    }, 500)
  }

  // 加载图片
  const loadImage = (canvasEle: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => {
    const img = new Image();

    img.src = currentUrlRef.current;
    ctx.drawImage(img, 0, 0, canvasEle.width, canvasEle.height)
  }

  // 开始画图
  const beginDraw = (type: string) => {
    const exits = exitTypes.current;
    if (!exits.includes(type)) {
      drawFlag.current = true;

      // 画图类型
      const drawType = type === 'actArea' ? 'area' : 'rectangle'
      drawTypeFlag.current = drawType;

      exits.push(type)
      exitTypes.current = exits;
    } else {
      message.warning('已存在相同类型画图！')
    }
  }

  // clonePoints
  const cloneAreaPoints = (point: CoordinateState) => {
    const points = areaPointsRef.current;
    if (points.length > 0) {
      const { x, y } = point;
      const { x: x1, y: y1 } = points[points.length - 1];
      if (x === x1 && y === y1) {
        return false;
      }
    }

    points.push(point)

    if(points.length===2 && drawTypeFlag.current === 'rectangle'){
      stopDraw()
    }

    setAreaPoints(points)

    return true;

  }


  // 开始画图
  const startDraw = (e: MouseEvent, type: EventsType) => {
    if (drawFlag.current) {
      const x = e.offsetX; // 鼠标落下时的X
      const y = e.offsetY; // 鼠标落下时的Y
      // console.log(x, y, type);
      if (type !== 'move') {
        cloneAreaPoints({ x, y })
      } else {
        setCurrentMovePoint({ x, y })
      }

    }
  }

  

  // 给canvas画布添加事件
  const addCanvasEvents = () => {
    const canvasEle: CanvasElementState = document.querySelector('#myCanvas');
    if (canvasEle) {
      /**
       * 绑定点击事件
       */
      canvasEle.addEventListener('mousedown', e => {
        startDraw(e, 'click');
      });
      /**
       * 绑定双击事件
       */
      canvasEle.addEventListener('dblclick', e => {
        startDraw(e, 'dblclick');
        stopDraw()
      });

      /**
       * 绑定鼠标移动事件
       */
      canvasEle.addEventListener('mousemove', e => {
        startDraw(e, 'move');
      });

    }
  }

  useEffect(() => {

    const canvasEle: CanvasElementState = document.querySelector('#myCanvas');
    if (canvasEle && areaPoints.length > 0) {

      const ctx = canvasEle.getContext('2d');
      if (ctx) {
        // 清除画布
        ctx.clearRect(0, 0, canvasEle.width, canvasEle.height);
        // 填充上一次的画图
        if (currentUrlRef.current) loadImage(canvasEle, ctx)
        // 准备画图
        ctx.beginPath();
        ctx.strokeStyle = '#ff0000';

        // 判断是不规则还是规则画图
        let drawerPoints: CoordinateState[] = []
        if (drawTypeFlag.current === 'area') {
          drawerPoints = areaPoints;
        } else {
          const { x, y } = areaPoints[0];
          const current = areaPoints.length > 1 ? areaPoints[1] : currentMovePoint;
          if (current) {
            const { x: x1, y: y1 } = current;
            drawerPoints = [
              { x, y },
              { x, y: y1 },
              { x: x1, y: y1 },
              { x: x1, y }
            ]
          }
        }

        // 开始画图
        ctx.moveTo(drawerPoints[0].x, drawerPoints[0].y);
        for (let i = 1; i < drawerPoints.length; i += 1) {
          ctx.lineTo(drawerPoints[i].x, drawerPoints[i].y);
        }
        // 如果有移动点位
        if (currentMovePoint && drawTypeFlag.current === 'area') {
          ctx.lineTo(currentMovePoint.x, currentMovePoint.y);
        }
        // 闭合
        ctx.closePath();
        // ③绘制
        ctx.stroke();
      }
    }

  }, [areaPoints, currentMovePoint])




  useEffect(() => {
    addCanvasEvents();

  }, [])




  return (
    <div>
      <Space size="small" direction="horizontal">
        <Button
          type="primary"
          onClick={() => {
            beginDraw('actArea');
          }}
        >
          画不规则区域
        </Button>
        <Button
          type="primary"
          onClick={() => {
            beginDraw('minArea');
          }}
        >
          最小区域
        </Button>
        <Button
          type="primary"
          onClick={() => {
            beginDraw('maxArea');
          }}
        >
          最大区域
        </Button>
        <Button
          type="primary"
          onClick={() => {
            clearAll()
          }}
        >
          清除
        </Button>
      </Space>
      <canvas
        id='myCanvas'
        width={800}
        height={600}
        style={{ border: '1px solid red', marginTop: 24 }} />
    </div>
  )
}

export default CanvasImage;